#pragma once

#ifdef __cplusplus
        #define EXTERN_C extern "C" {
#else
        #define EXTERN_C extern 
#endif


#ifdef __cplusplus
        #define EXTERN_C_END }
#else
        #define EXTERN_C_END  
#endif

EXTERN_C

// Очищаем структуру Expression
void CleanStructExpression(struct Expression * expr);

//создание выражение для id
struct Expression * CreateIdentifierExpr(char * id);

// создание выражения Const
struct Expression * CreateConstantExpr(int constant);

// создание выражения Char
struct Expression * CreateCharExpr(char c);

// создание выражения String
struct Expression * CreateStringExpr(char * string);

// бинарные операции
struct Expression * CreateBinaryExpr(enum ExprType type, struct Expression *left_expr, struct Expression *right_expr);

// унарные операции
struct Expression * CreateUnaryExpr(enum ExprType type, struct Expression *expr);

// доступ к полю метода
struct Expression * CreateIntanceVariableAccessExpr(struct Expression * object, char * field);

// вызов функции
struct Expression * CreateFunctionCallExpr(char * function_name, struct ExpressionList * args);

// сообщения
struct Expression * CreateKeywordMessageExpr(char * selector_name, struct Expression * expr);

// создание NEW
struct Expression * CreateNewExpr(char *id);

//вызов метода
struct Expression * CreateMethodCallExpr(enum CallObjectType object_type, struct Expression * object, char * method_name);

//вызов метода с параметрами
struct Expression * CreateMethodCallArgsExpr(enum CallObjectType object_type, struct Expression * object, struct ExpressionList * arguments);

//создание экспра на основе self
struct Expression * CreateSelfExpr();

// создание списка аргументов
struct ExpressionList * CreateExpressionList(struct Expression * expr);

// добавление в список аргументов
struct ExpressionList * AddToExpressionList(struct ExpressionList * list, struct Expression * expr);

// создание списка аргументов
struct ExpressionList * CreateArgumentsList(struct Expression * expr);

// добавление в список аргументов
struct ExpressionList * AddToArgumentsList(struct ExpressionList * list, struct Expression * expr);

// создание списка сообщений
struct ExpressionList * CreateMessagesList(char * id, struct Expression * expr);

// добавление в список аргументов
struct ExpressionList * AddToMessagesList(struct ExpressionList * list, char * id, struct Expression * expr);

//!-- STMT
void CleanStructStatement(struct Statement * stmt);

// создать составной стейтмент
struct Statement * CreateCompoundStatement(struct StatementList *list);

// создать стейтмент из expr'а
struct Statement * CreateExprStatement(struct Expression *expr);

// создать условие
struct Statement * CreateIfStatement(struct Expression *condition, struct Statement *true_stmt, struct Statement *false_stmt);

// создать switch
struct Statement * CreateSwitchStatement(struct Expression *condition, struct LabeledStatementList *labeled_list);

// создать цикл while
struct Statement * CreateWhileStatement(enum StmtType type, struct Expression *condition, struct Statement *stmt);

// создать цикл for
struct Statement * CreateForStatement(struct Expression *precondition, struct Expression *condition, struct Expression *postcondition, struct Statement *stmt);

// создать оператор перехода
struct Statement * CreateJumpStatement(enum StmtType type, struct Expression *expr);

//создать оператор из объявления
struct Statement * CreateVariableDeclarationStatement(struct VariableDeclaration * vardecl);

void cleanLabeledStatement(struct LabeledStatement *lstmt);

struct LabeledStatement * CreateLabeledStatement(enum LabeledStatementType type, struct Expression * expr, struct StatementList * list);

// создание списка
struct LabeledStatementList * CreateLabeledStatementList(struct LabeledStatement * stmt);

// добавление в лист
struct LabeledStatementList * AddToLabeledStatementList(struct LabeledStatementList * list, struct LabeledStatement * stmt);

// создание списка аргументов
struct StatementList * CreateStatementList(struct Statement *stmt);

// добавление в список аргументов
struct StatementList * AddToStatementList(struct StatementList * list, struct Statement *stmt);

//объявление enum'а
struct EnumDeclaration * CreateEnumDeclaration(char *id, struct EnumeratorList * list);

// создание списка вариантов Enum'а
struct EnumeratorList * CreateEnumeratorList(char * id);

// добавление в список вариантов enum'а
struct EnumeratorList * AddToEnumeratorList(struct EnumeratorList * list, char * id);

// создать тип
struct Type * CreateType(enum TypeVariant type, char * id);

void cleanVariableDeclaration(struct VariableDeclaration * vardecl);

// создание переменной
struct VariableDeclaration * CreateVariableDeclaration(enum VariableDeclarationType type, struct Type * variable_type, char *name, int size, char *part_name);

// создание списка переменных
struct VariableDeclarationList * CreateVariableDeclarationList(struct VariableDeclaration * vardecl);

// добавление в список переменных
struct VariableDeclarationList * AddToVariableDeclarationList(struct VariableDeclarationList * list, struct VariableDeclaration * vardecl);

// создать декларатор
struct Declarator * CreateDeclarator(enum DeclaratorType type, char *id, struct VariableDeclarationList * list);

void cleanDeclarationDefinition(struct DeclarationDefinition * decldef);

// создать описание\определение метода
struct DeclarationDefinition * CreateMethodDeclarationDefinition(enum DeclType type, struct Type *typeName, struct Declarator *name, struct Statement * compoundStmt);

// создать определение функции
struct FunctionDefinition * CreateFunctionDefinition(struct Type *type, char *name, struct VariableDeclarationList * parameters, struct Statement * compoundStmt);

// создание списка методов
struct DeclarationDefinitionList * CreateDeclarationDefinitionList(struct DeclarationDefinition * decldef);

// добавление в список
struct DeclarationDefinitionList * AddToDeclarationDefinitionList(struct DeclarationDefinitionList * list, struct DeclarationDefinition * decldef);

// создать информацию о классе
struct ClassInfo * CreateClassInfo(enum ClassInfoType type, char * name, char * parent, struct VariableDeclarationList * instanceVariables, struct DeclarationDefinitionList * methods);

void cleanExternalDeclaration(struct ExternalDeclaration * result);

// создать внешнее объявление - функцию
struct ExternalDeclaration * CreateFuncExternalDeclaration(struct FunctionDefinition * func);

// создать внешнее объявление - класс
struct ExternalDeclaration * CreateClassExternalDeclaration(enum ExternalDeclarationType type, struct ClassInfo * class_info);

// создать внешнее объявление - enum
struct ExternalDeclaration * CreateEnumExternalDeclaration(struct EnumDeclaration * decl);

// создание списка внешних объявлений
struct ExternalDeclarationList * CreateExternalDeclarationList(struct ExternalDeclaration * decl);

// добавление в список внешних объявлений
struct ExternalDeclarationList * AddToExternalDeclarationList(struct ExternalDeclarationList * list, struct ExternalDeclaration * decl);

EXTERN_C_END